package com.example.demo.kafka;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;

public class KafkaProducerTest {

    private static final String BOOTSTRAP_SERVERS = "192.168.0.101:9092";

    public static void main(String[] args) {
        Properties props = new Properties();
        props.put("bootstrap.servers", BOOTSTRAP_SERVERS);
        /**
         * acks=0
         * 如果设置为0，那么生产者将根本不等待来自服务器的任何确认。该记录将立即添加到套接字缓冲区并被认为已发送。在这种情况下，不能保证服务器已经收到了记录，并且重试配置将不会生效(因为客户机通常不知道任何失败)。每个记录返回的偏移量将始终设置为-1。
         * acks=1
         * 这将意味着leader将记录写入本地日志，但不会等待所有追随者的完全确认。在这种情况下，如果leader在确认记录后立即失败，但在follower复制它之前，那么记录将丢失。
         * acks=all
         * 这意味着leader将等待全部同步副本来确认该记录。这保证了只要至少有一个同步副本存活，记录就不会丢失。这是最有力的保证。这相当于acks=-1设置
         */
        props.put("acks", "all");
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        /**
         * 生产者可以用来缓冲等待发送到服务器的记录的总内存字节。如果记录发送的速度比发送到服务器的速度快，生成器将阻塞max.block.ms，然后抛出异常。
         * 这个设置应该大致对应于生产者将使用的总内存，但不是一个硬限制，因为不是所有生产者使用的内存都用于缓冲。一些额外的内存将用于压缩(如果启用了压缩)以及维护运行中的请求。
         */
//		 props.put("buffer.memory", 33554432l);
        /**
         * 生产者生成的所有数据的压缩类型。默认值是none(即没有压缩)。有效值为none、gzip、snappy、lz4或zstd。压缩是全批数据，因此批处理的有效性也会影响压缩比(批处理越多意味着压缩效果越好)。
         */
//		 props.put("compression.type", "none");
        /**
         * 设置一个大于零的值将导致客户端重新发送任何发送失败的记录，并可能出现短暂错误。请注意，此重试与客户端在接收到错误时重发记录没有区别。在不将max.in.flight.requests.per.connection设置为1的情况下允许重试可能会改变记录的顺序，因为如果将两个批发送到同一个分区，第一个批失败并重试，但第二个批成功，那么第二个批中的记录可能会先出现。请注意，如果由delivery.timeout.ms配置的超时时间在成功确认之前先过期，那么所有产生的请求将在重试次数耗尽之前失败。用户通常应该不设置此配置，而使用delivery.timeout.ms来控制重试行为。
         */
        props.put("retries", 0);
        /**
         * 此配置控制默认批处理大小(以字节为单位)。不会尝试批处理大于此大小的记录。
         */
//		 props.put("batch.size", 16384);

        /**
         * 在发出请求时传递给服务器的id字符串。这样做的目的是允许在服务器端请求日志记录中包含逻辑应用程序名，从而能够跟踪ip/port以外的请求源。
         */
//		 props.put("client.id", "");

        /**
         * 在此配置指定的毫秒数后关闭空闲连接
         */
//		 props.put("connections.max.idle.ms", 540000L);
        /**
         * 调用send()返回后报告成功或失败的时间上限。这限制了记录在发送之前被延迟的总时间、等待代理确认的时间(如果预期)以及允许可恢复的发送失败的时间。如果遇到不可恢复的错误，重试已耗尽，或者记录被添加到达到较早交付过期期限的批处理中，生产者可能会报告发送比此配置早的记录失败。该配置的值应该大于或等于request.timeout.ms和linger.ms的和。
         */
//		 props.put("delivery.timeout.ms", 120000);
        /**
         * 生产者将在请求传输之间到达的任何记录组合为单个批处理请求。通常情况下，这只会发生在负载情况下，即记录到达的速度比发送的速度快。然而，在某些情况下，即使在中等负载下，客户端也可能希望减少请求的数量。该设置通过添加少量的人工延迟来实现这一点——也就是说，生产者不会立即发送一条记录，而是等待指定的延迟时间，以允许发送其他记录，这样发送的记录就可以被批处理在一起。这可以被认为类似于TCP中的Nagle算法。这个设置给出了批处理延迟的上限:一旦我们获得批处理。一个分区的记录大小将被立即发送，不管这个设置是什么，但是如果这个分区的累积字节数少于这个数，我们将在指定的时间内“逗留”，等待更多的记录出现。这个设置默认为0(即没有延迟)。设置徘徊。例如，Ms
         * =5可以减少发送的请求数量，但在没有负载的情况下会增加高达5ms的发送记录延迟。
         */
        props.put("linger.ms", 1);
        /**
         * 配置控制KafkaProducer.send()和KafkaProducer.partitionsFor()阻塞的时间。这些方法可能因为缓冲区已满或元数据不可用而被阻塞。在用户提供的序列化器或分区器中阻塞将不计入此超时。
         */
//		 props.put("max.block.ms", 60000l);

        Producer<String, String> producer = new KafkaProducer<>(props);

        for (int i = 0; i < 100; i++) {
            producer.send(
                    new ProducerRecord<String, String>("quickstart-events", Integer.toString(i), Integer.toString(i)));
        }
        producer.close();
    }
}
